﻿namespace Hervey
{
    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;

    public class IniHelper
    {
        /// <summary>
        /// 使用demo   （变量与本地之间）
        /// </summary>
        /*             
        ini = new IniHelper("D:\\1.ini");
        ini.InitIniFile<Para>();//初始化为Description特性的值
        ini.SetValue("section", "key1", 2);//单独修改某一个
        Para p = ini.GetValue<Para>();//读取参数
        p.ID = 1;
        p.User = 管理员;
        ini.SetValue<Para>(p);//全部更新
        */

        private string sPathFile;
        private FileInfo fileinfo;


        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string lpApplicationName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);


        public IniHelper(string sPath)
        {
            this.sPathFile = sPath.Substring(0, sPath.LastIndexOf(@"\"));
            if (!Directory.Exists(this.SPathFile))
            {
                Directory.CreateDirectory(this.SPathFile);
            }
            this.fileinfo = new FileInfo(sPath);
            if (!this.fileinfo.Exists)
            {
                new StreamWriter(sPath).Close();
            }
            this.SPathFile = sPath;
        }


        public void InitIniFile(object section, object key, object value)
        {
            try
            {
                if (this.GetValue(section, key) == "")
                {
                    this.SetValue(section, key, value);
                }
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
            }
        }

        public void InitIniFile<T>(string section="")
        {
            try
            {
                Type t = typeof(T);
                if(string.IsNullOrWhiteSpace(section))section = t.Name;
                PropertyInfo[] info = t.GetProperties();
                foreach (var item in info)
                {
                    Type ty = item.PropertyType;
                    string s = GetValue(section, item.Name);
                    if (string.IsNullOrWhiteSpace(s))
                    {
                        DescriptionAttribute val = (DescriptionAttribute)item.GetCustomAttribute(typeof(DescriptionAttribute), true);
                        if (val != null)
                        {
                            object objVal="";
                            if(ty.Equals(typeof(string)))
                            {
                                objVal = val.Description.Trim();
                            }
                            else if(ty.Equals(typeof(int)))
                            {
                                int n;
                                if (!int.TryParse(val.Description, out n)) objVal = 0;
                                else objVal = n;
                                
                            }
                            else if (ty.Equals(typeof(double)))
                            {
                                double n;
                                if (!double.TryParse(val.Description, out n)) objVal = 0;
                                else objVal = n;
                            }
                            else if (ty.Equals(typeof(bool)))
                            {
                                bool b;
                                if (!bool.TryParse(val.Description, out b)) objVal = false;
                                else objVal = b;
                            }
                            else
                            {
                                objVal = val.Description.Trim();
                            }
                            SetValue(section, item.Name, objVal);
                        }
                        else SetValue(section, item.Name, "");
                    }
                }
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
            }

        }

        public string GetValue(object Section, object Key)
        {
            try
            {
                StringBuilder lpReturnedString = new StringBuilder(500);
                byte[] buffer = new byte[0x400];
                GetPrivateProfileString(Section.ToString(), Key.ToString(), "", lpReturnedString, 500, this.sPathFile);
                return lpReturnedString.ToString();
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
                return "Err";
            }

        }

        public T GetValue<T>(string section = "")
        {
            try
            {
                T tInstance = Activator.CreateInstance<T>();
                Type t = typeof(T);
                if (string.IsNullOrWhiteSpace(section)) section = t.Name;
                PropertyInfo[] info = t.GetProperties();
                foreach (var item in info)
                {
                    object val = GetValue(section, item.Name);
                    Type tItem = item.PropertyType;
                    if (tItem.Equals(typeof(Int16)) || tItem.Equals(typeof(Int32)) || tItem.Equals(typeof(Int64)))
                    {
                        item.SetValue(tInstance, Convert.ToInt32(val));
                    }
                    else if (tItem.Equals(typeof(string)))
                    {
                        item.SetValue(tInstance, Convert.ToString(val));
                    }
                    else if (tItem.Equals(typeof(bool)))
                    {
                        item.SetValue(tInstance, Convert.ToBoolean(val));
                    }
                    else if (tItem.Equals(typeof(double)))
                    {
                        item.SetValue(tInstance, Convert.ToDouble(val));
                    }

                }
                return tInstance;
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
                return Activator.CreateInstance<T>();
            }
        }

        public void SetValue(object Section, object Key, object Value)
        {
            try
            {
                WritePrivateProfileString(Section.ToString(), Key.ToString(), Value.ToString(), this.sPathFile);
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
            }
        }

        public void SetValue<T>(T tInstance, string section = "")
        {
            try
            {
                Type t = typeof(T);
                if (section == "") section = t.Name;
                PropertyInfo[] info = t.GetProperties();
                foreach (var item in info)
                {
                    object val = item.GetValue(tInstance);
                    if(val !=null)SetValue(section, item.Name, val);
                }
            }
            catch (Exception ex)
            {
                Log((new System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name, ex.Message);
            }
        }


        public string ReadFile()
        {
            StreamReader reader = new StreamReader(this.sPathFile);
            string str = reader.ReadToEnd();
            reader.Close();
            return str;
        }

        public void WriteFile(object strValue)
        {
            StreamWriter writer = new StreamWriter(this.sPathFile);
            writer.Write(strValue.ToString().Replace("\n", Environment.NewLine));
            writer.Close();
        }

        public string SPathFile
        {
            get
            { return this.sPathFile; }
               
            set
            {
                this.sPathFile = value;
            }
              
        }



        private void Log(string method, string msg)
        {
            try
            {
                string path = Path.Combine(Environment.CurrentDirectory, "ErrIniHelper.txt");
                using (StreamWriter sw = new StreamWriter(path, true))
                {
                    string str = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ");
                    str += method + " " + msg;
                    sw.WriteLine(str);
                }
            }
            catch (Exception)
            {

            }

        }
    }
}

